package com.sti.framework.models.User.controller;

import com.sti.framework.core.security.jwt.JwtUtil;
import com.sti.framework.core.web.ResponseBodyEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;

@Api(tags = "图片编码工具")
@RestController
@RequestMapping("/Api")
public class CaptchaController {

    /**
     * 获取登录图片验证码
     */
    @ApiOperation(value = "获取登录图片验证码")
    @GetMapping("/User/Captcha")
    public ResponseBodyEntity<ValidBase64CodeVO> getCaptchaCode() {
        CaptchaUtil instance = CaptchaUtil.getInstance();
        // 验证码标识
        String key = JwtUtil.geneCaptcha(instance.getCode());

        // 将图像输出到Servlet输出流中。
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(instance.getBuffImg(), "jpeg", out);
            return ResponseBodyEntity.success(new ValidBase64CodeVO(Base64Utils.encodeToString(out.toByteArray()), "image/jpeg", key));
        } catch (IOException e) {
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "验证码生成错误！");
        }
    }
}

/**
 * base64的图片验证码
 * @author chenxiaoqi
 * @since 2021/03/03
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
class ValidBase64CodeVO {
    @ApiModelProperty(value = "base64图片")
    private String base64;
    @ApiModelProperty(value = "类型",example = "image/jpeg")
    private String mediaType;
    @ApiModelProperty(value = "验证key(解密后可以获得图片内容)")
    private String validateKey;
}

class CaptchaUtil {

    private BufferedImage buffImg;
    private String code;

    // 图片的宽度
    private static final int CAPTCHA_WIDTH = 90;
    // 图片的高度
    private static final int CAPTCHA_HEIGHT = 20;
    // 验证码的个数
    private static final int CAPTCHA_CODECOUNT = 4;

    private static final int XX = 15;
    private static final int CAPTCHA_FONT_HEIGHT = 18;
    private static final int CAPTCHA_CODE_Y = 16;
    private static final char[] CODE_SEQUENCE = {
            'a', 'b', 'c', 'd', 'e', 'f', 'g',
            'h', 'j', 'k', 'm', 'n',
            'p', 'q', 'r', 's', 't',
            'u', 'v', 'w', 'x', 'y', 'z',
            '2', '3', '4', '5', '6', '7', '8', '9' };

    // 过期时间为60秒
    private static final long EXPIRE_MINUTES = 60;

    private CaptchaUtil() {
        // 定义图像 Buffer
        buffImg = new BufferedImage(CAPTCHA_WIDTH, CAPTCHA_HEIGHT, BufferedImage.TYPE_INT_RGB);
        // 创建一个绘制图像的对象
        Graphics2D g = buffImg.createGraphics();
        // 创建一个随机数生成器类
        Random random = new Random();
        // 将图像填充为白色
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, CAPTCHA_WIDTH, CAPTCHA_HEIGHT);
        // 设置字体
        g.setFont(new Font("Fixedsys", Font.BOLD, CAPTCHA_FONT_HEIGHT));
        // 设置字体边缘光滑
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 画边框
        //        g.setColor(Color.BLACK);
        //g.drawRect(0, 0, CAPTCHA_WIDTH - 1, CAPTCHA_HEIGHT - 1);
        // 随机产生5条干扰线，使图象中的认证码不易被其它程序探测到。
        g.setColor(Color.BLACK);
        for (int i = 0; i < 5; i++) {
            int x = random.nextInt(CAPTCHA_WIDTH);
            int y = random.nextInt(CAPTCHA_HEIGHT);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }

        // 保存随机产生的验证码，以便用户登录后进行验证
        StringBuilder randomCode = new StringBuilder();
        int red = 0, green = 0, blue = 0;
        // 随机产生验证码
        for (int i = 0; i < CAPTCHA_CODECOUNT; i++) {
            // 得到随机产生的验证码数字
            String code = String.valueOf(CODE_SEQUENCE[random.nextInt(CODE_SEQUENCE.length)]);
            // 产生随机的颜色分量来构造颜色值，这样输出的每位数字的颜色值都将不同
            red = random.nextInt(255);
            green = random.nextInt(255);
            blue = random.nextInt(255);
            // 用随机产生的颜色将验证码绘制到图像中
            g.setColor(new Color(red, green, blue));
            g.drawString(code, (i + 1) * XX, CAPTCHA_CODE_Y);
            // 将产生的随机数组合在一起
            randomCode.append(code);
        }
        code = randomCode.toString();
    }

    public static CaptchaUtil getInstance(){
        return new CaptchaUtil();
    }

    public BufferedImage getBuffImg() {
        return buffImg;
    }

    public String getCode() {
        return code;
    }
}
